import json
import os
import re

from django.db.models import F
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
import random

from django.core.serializers import serialize
from django.views import View
from rest_framework.response import Response
from rest_framework.views import APIView

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT

from mydjango import settings

#导入redis数据库
from .utils import redis

from mydjango import settings

#导入时间模块
import time
from .models import WorkType, Work, Task,User

from .check_authority import manage_work
from django.utils.decorators import method_decorator

# 导包查询数据库
from .utils import MysqlFind

# 导入jwt加密和解密方法
from .utils import make_jwt, chack_jwt, get_uid, base64encode, uploadFile, DingInform, redis1

from .md_message import clients

from django.db import transaction




# 工单类型的增删改查
class WorkTypeApi(APIView):
    @method_decorator(manage_work)
    def post(self, request):
        # 验证参数
        name = request.data.get("name")
        custom = request.data.get("custom")
        approver = request.data.get("approver")
        print(custom,approver)
        if not all([name, custom, approver]):
            return Response({"code": 999, "data": "参数不齐"})
        for i in custom:
            if not i:
                return Response({"code": 999, "data": "参数不齐"})
        for i in approver:
            if not i:
                return Response({"code": 999, "data": "参数不齐"})

        # 把前端发送的数据转换为json格式
        custom = json.dumps(custom, ensure_ascii=False)
        approver = json.dumps(approver)
        # try:
        #     WorkType.objects.create(name=name, custom=custom, approver=approver)
        # except Exception as e:
        #     return Response({"code": 999, "data": '已经有该类型'})

        return Response({"Code":200, "data": "添加成功", "log": "添加工单类型：%s" % name})

    def get(self, request):
        wid = request.GET.get("wid", None)
        if not wid == "undefined":
            work_obj = WorkType.objects.get(pk=int(wid))

            work_data = {"key": work_obj.id, "id": work_obj.id, "name": work_obj.name, "custom": json.loads(work_obj.custom),
                      "approver": json.loads(work_obj.approver)}

            return Response({"code": 200, "data": work_data})

        else:
            work_obj = WorkType.objects.all()
            work_data = [{"key":i.id,"id":i.id, "name": i.name, "custom": i.custom, "approver": json.loads(i.approver)} for i in work_obj]
            return Response({"code": 200, "data": work_data})

    @method_decorator(manage_work)
    def delete(self, request):
        wid = request.data.get("wid")
        work_obj = WorkType.objects.get(pk=wid)
        name = work_obj.name
        work_obj.delete()
        return Response({"code":200, "data": "删除成功", "log": "删除了%s工单类型" % name})

    @method_decorator(manage_work)
    def put(self, request):
        wid = request.data.get("wid")
        name = request.data.get("name")
        custom = request.data.get("custom")
        approver = request.data.get("approver")

        if not all([wid, name, custom, approver]):
            return Response({"code": 999, "data": "参数不齐"})

        work_obj = WorkType.objects.get(pk=wid)
        # 把前端发送的数据转换为json格式
        custom = json.dumps(custom, ensure_ascii=False)
        approver = json.dumps(approver)
        work_obj.name = name
        work_obj.custom = custom
        work_obj.approver = approver

        return Response({"code": 200, "data": "修改成功", 'log': "将%s的工单类型修改" % work_obj.name})


# 用户添加工单
class WorkApi(APIView):

    def post(self, request):
        # 获取参数
        data = request.data.get("fields_data")
        wid = request.data.get("wid")
        img = request.data.get("img")
        data = json.dumps(data, ensure_ascii=False)
        token = request.META.get("HTTP_AUTHORIZATION", None)
        token = token[4:]
        uid = chack_jwt(token).get("uid")

        # 存入工单库
        # {"endtime": "2020-10-21", "starttime": "2020-10-22", "原因": "生病"}

        # 转换为base64存入mysql中，mysql字段设置为mediumtext可以存储16MB
        with open(os.path.join(UPLOAD_ROOT, '', img), 'rb') as f:
            base64img = base64encode(f)
            upyunimg =uploadFile(img, f)

        work_obj = Work(user_id=uid, work_data=data, work_type_id=wid, img=settings.Django_URL+'static/upload/'+img, base64img=base64img,upyunimg='http://work-image.test.upcdn.net/'+img)
        work_obj.save()

        # 根据工单类型获取审批人的列表
        worktype_obj = WorkType.objects.get(pk=wid)
        user_list = json.loads(worktype_obj.approver)

        # 循环审批人的列表，进行任务数据的创建
        # 循环列表的下标
        for index in range(len(user_list)):
            task_obj = Task(work_id=work_obj.id, uid=user_list[index])
            task_obj.save()
            if index == 0:
                work_obj.next_id = task_obj.id
                work_obj.save()

        return Response({"code": 200, "data": "添加成功", 'log': "申请了%s类型的工单" % work_obj.name})






# 任务
class TaskApi(APIView):

    def get(self, request):
        # 根据token获取用户的uid
        token = request.META.get("HTTP_AUTHORIZATION")
        token = token[4:]
        uid = chack_jwt(token).get("uid")

        # 查数据库
        sql = "select d.name, c.username, a.uid, a.id, b.work_data from task as a left join work as b on a.work_id=b.id left join user as c on b.user_id = c.id left join worktype as d on b.work_type_id = d.id where b.next_id = a.id and a.state=0 and FIND_IN_SET('%s', a.uid)" % uid
        result = MysqlFind(sql).sql_select()
        print(123)
        print(result)

        return Response({"code": 200, "data": result})

    # 审批人审批接口
    def put(self, request):
        # 获取前端的数据，同意或拒绝，工单id，任务id
        type = request.data.get("type")
        work_id = request.data.get("work_id")
        task_id = request.data.get("task_id")
        refuse = request.data.get("refuse_")
        username = request.data.get("username")
        print(type, work_id, task_id, refuse, username)

        # 如果拒绝就直接修改成2返回
        if type == "拒绝":
            # 修改是进行查询，如果返回为0，则表示数据已经被修改，返回任务已经不存在
            with transaction.atomic():
                task_obj = Task.objects.filter(pk=task_id, state__lt=0)
                if not task_obj:
                    return Response({"code": 999, "msg": "任务已经不存在"})
                task_obj.update(state=2)
                task_obj.first().refuse = refuse
                task_obj.first().save()

            # 把工单表的next_id改为0
            work_obj = Work.objects.get(pk=work_id)
            work_obj.next_id = 0
            work_obj.save()

            # 查询数据然后使用钉钉机器人发送到钉钉群
            sql = "select a.refuse,c.name,d.username,d.phone,b.upyunimg,d.id, b.user_id  from task as a left join work as b on a.work_id=b.id left join worktype as c on b.work_type_id=c.id left join user as d on b.user_id=d.id where b.id=" + str(
                work_id) + ' and a.id=' + str(task_id)
            result = MysqlFind(sql).sql_select()[0]
            content = '### 审批意见 \n > 尊敬的' + username + ',你的' + result.get('name') + '申请已经被' + result.get(
                'username') + '拒绝了。\n审批意见:' + result.get('refuse') + '\n![](' + result.get('upyunimg') + ')'

            # DingInform().send_ding(content, result.get('phone'))

            uid = result.get("id")
            if uid in clients.keys():
                res = len(redis.hgetall(uid))
                print("redis长度", res)
                if res > 0:
                    clients.get(uid).send(str(res).encode("utf-8"))

            # 将审批情况存入redis中
            redis_content = "审批情况：尊敬的"+username+"你的"+ result.get('name') + '申请已经被' + result.get(
                'username') + '拒绝了。审批意见:' + result.get('refuse')
            redis.hset(result.get("user_id"), task_id, redis_content)

                # clients[uid].send(data.encode('utf-8'))
            # 如果没在线,就不修改is_read,等到用户上线后在websocketlink中直接进行推送

            return Response({"code": 200, "data": "已经拒绝", "log": "拒绝了%s的%s工单申请" % (username, result.get("name"))})

        # 同意的话就吧状态改成1，并填入审批意见查询下一条任务的id
        # 同意的话把状态改为1，下一条审批id可能是多个使用FIND_IN_SET
        #
        with transaction.atomic():

            task_obj = Task.objects.filter(pk=task_id,state__lte=1)
            print(task_obj)

            if not task_obj:
                return Response({"code": 999, "msg": "任务已经不存在"})
            task_obj.update(state=1)
            task_obj.first().refuse = refuse
            task_obj.first().save()
        sql = "select b.id from work as a left join task as b on a.id=b.work_id where a.id=" + str(work_id) + " and state=0 limit 1"
        result = MysqlFind(sql).sql_select()
        work_obj = Work.objects.get(pk=work_id)
        if result:
            next_id = result[0].get("id")
            work_obj.next_id = next_id
            work_obj.save()
        else:
            work_obj.next_id = 0
            work_obj.save()
            # 将请假次数存入redis中
            redis1.zincrby("leave", 1, username)

        # b.user_id是work表对应的用户id，也就是任务发起人的id
        sql = "select a.refuse,c.name,d.username,d.phone,b.upyunimg,d.id, b.user_id  from task as a left join work as b on a.work_id=b.id left join worktype as c on b.work_type_id=c.id left join user as d on a.uid=d.id where b.id=" + str(
            work_id) + ' and a.id=' + str(task_id)
        result = MysqlFind(sql).sql_select()[0]

        # 发送钉钉机器人
        content = '### 审批意见 \n > 尊敬的'+ username +',你的' + result.get('name') + '申请已经被' + result.get('username') + '同意了。\n审批意见:' + result.get('refuse') + '\n![]('+ result.get('upyunimg') +')'

        # DingInform().send_ding(content, result.get('phone'))

        # 如果用户在线直接发送信息
        uid = result.get("id")
        if uid in clients.keys():
            res = len(redis.hgetall(uid))
            print("redis长度", res)
            if res > 0:
                clients.get(uid).send(str(res).encode("utf-8"))

        # 将同意的情况存入到redis中
        # 在sql语句中查询出来的work表中对应的用户id当为大key，任务id作为key，审批语句作为value
        redis_content = "审批情况：尊敬的"+username+"你的"+ result.get('name') + '申请已经被' + result.get(
                'username') + '同意了。审批意见:' + result.get('refuse')
        redis.hset(result.get("user_id"), task_id, redis_content)

        # 如果没在线,就不修改is_read,等到用户上线后在websocketlink中直接进行推送
        return Response({"code": 200, "data": "已同意", "log": "同意了%s的%s工单申请" % (username, result.get("name"))})


# 用户审批的工单详情
class GetOneWork(APIView):

    def get(self, request):
        # 格局任务id查询申请人用户名，工单信息，工单类型，方便前端回调任务同意或失败,
        task_id = request.GET.get("task_id")
        sql = "select b.work_data,b.id, c.username,d.name from task as a left join work as b on a.work_id=b.id left join user as c on b.user_id=c.id left join worktype as d on d.id=b.work_type_id where state=0 and a.id=" + str(task_id)
        result = MysqlFind(sql).sql_select()
        if result:
            result = result[0]
            result["work_data"] = json.loads(result["work_data"])

            # 任务id肯定是唯一的，所以直接使用下标取出第一个
            return Response({"code": 200, "data": result})
        else:
            return Response({"code": 200, "data": "没有任务"})


# 用户申请的工单
class MyWorkApi(APIView):

    def get(self, request):
        token = request.META.get("HTTP_AUTHORIZATION")[4:]
        print("tokentye", type(token))
        uid = get_uid(request)
        work_id = request.GET.get("work_id")
        if work_id != "undefined":
            print(111)
            sql = "select a.img,a.upyunimg,a.work_data,b.refuse, a.next_id, b.state, c.username from work as a left join task as b on a.id=b.work_id left join user as c on b.uid=c.id where a.id=" + str(work_id)
            result = MysqlFind(sql).sql_select()

        else:
            sql = "select a.img, a.base64img,a.upyunimg, a.id, a.work_data, b.name from work as a left join worktype as b on a.work_type_id=b.id left join user as c on a.user_id=c.id where c.id=" + str(uid)
            result = MysqlFind(sql).sql_select()

        # 吧work_data转换为json
        for i in result:
            i['work_data'] = json.loads(i['work_data'])
            i["type"] = i['img'].split('.')[-1]
        return Response({"code": 200, "data": result})


class UploadFile(View):

    # 上传方法
    def post(self, request):
        #接收参数112
        img = request.FILES.get('file')

        # 建立文件流
        with open(os.path.join(UPLOAD_ROOT, '', img.name), 'wb') as f:
            for chunk in img.chunks():
                # print(chunk)
                f.write(chunk)

        return HttpResponse(json.dumps({"filename": img.name},ensure_ascii=False), content_type='application/json')


# 删除本地的图片
class Deleteimg(APIView):

    def delete(self, request):

        img_name = request.data.get("img_name")
        os.remove(os.path.join(UPLOAD_ROOT, '', img_name))


        return Response({"code": 200})


# 获取排行榜
class GetRanking(APIView):

    def get(self, request):
        res = redis1.zrange("leave", 0, 9, withscores=True, desc=True)
        redis1.publish("workflow", "hello")

        return Response({"code": 200, "data": res})





